package com.example.jdbc;

import com.example.util.JDBCUtils;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

/**
 * @program: sms
 * @description:
 * @author: zhanghz001
 * @create: 2020-11-09 14:52
 **/
public class MyDataSource implements DataSource {
    private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>());
    //改变一个对象的执行的方法,有很多种方法,继承,装饰器,适配器,动态代理

    //1
    // jdbc4Connection
    // static {
    //     for (int i = 0; i < 10; i++) {
    //         pool.add(JDBCUtils.getConnection());
    //     }
    // }
    //
    // @Override
    // public Connection getConnection() throws SQLException {
    //     if (pool.size() > 0) {
    //         Connection connection = pool.remove(0);
    //         //装饰器模式,在外面套一层,但是里面还是用的原来的东西
    //         // MyConnection myConnection = new MyConnection(JDBCUtils.getConnection(), pool);
    //         return connection;
    //     } else {
    //         throw new RuntimeException("连接池已经用尽");
    //     }
    // }

    //2
    // 配合装饰器模式,来解决问题.
    // static {
    //     for (int i = 0; i < 10; i++) {
    //         // MyConnection2 myConnection = new MyConnection2(JDBCUtils.getConnection(), pool);
    //         pool.add(JDBCUtils.getConnection());
    //     }
    // }
    //
    // @Override
    // public Connection getConnection() throws SQLException {
    //     if (pool.size() > 0) {
    //         Connection connection = pool.remove(0);
    //         //装饰器模式,在外面套一层,但是里面还是用的原来的东西
    //         MyConnection2 myConnection = new MyConnection2(JDBCUtils.getConnection(), pool);
    //         return myConnection;
    //     } else {
    //         throw new RuntimeException("连接池已经用尽");
    //     }
    // }

    // //适配器模式
    // static {
    //     for (int i = 0; i < 10; i++) {
    //         pool.add(JDBCUtils.getConnection());
    //     }
    // }
    //
    // @Override
    // public Connection getConnection() throws SQLException {
    //     if (pool.size() > 0) {
    //         Connection connection = pool.remove(0);
    //         //适配器模式
    //         MyConnection3 myConnection3 = new MyConnection3(connection, pool);
    //         return myConnection3;
    //     } else {
    //         throw new RuntimeException("连接池已经用尽");
    //     }
    // }

    //动态代理模式
    static {
        for (int i = 0; i < 10; i++) {
            pool.add(JDBCUtils.getConnection());
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        if (pool.size() > 0) {
            Connection connection = pool.remove(0);
            //动态代理
            InvocationHandler handler = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if ("close".equals(method.getName())) {
                        pool.add(connection);
                        return null;
                    } else {
                        return method.invoke(connection, args);
                    }
                }
            };
            Connection proxyCon = (Connection) Proxy.newProxyInstance(
                    connection.getClass().getClassLoader(),
                    new Class[]{Connection.class},
                    handler);
            return proxyCon;
        } else {
            throw new RuntimeException("连接池已经用尽");
        }
    }

    //
    public int getSize() {
        return pool.size();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}
